<?php

namespace App\Tools\Service;

use App\Models\CacheModel\ai_chat_room\AiChatRecordDetails;
use App\Models\CacheModel\ai_chat_room\AiChatTag;
use App\Models\CacheModel\AppConfig;
use Db;
use AstroTool\curl\Curl;

class AiChatRoomParse
{
    /**
     * 获取 流式会话结果
     * @return string
     */
    public static function getMsgParseStreamData(array $msgData, array $configData)
    {
        $url = Env::get('haozhungpt.url') . '/api/sentiment_chat';

        $resConfig = self::resertConfigData($configData);
        $chatConfig = (new AppConfig())->configInfo('ai_chat_room');
        $historyNum = (int)$chatConfig['history_num'];
        if ($historyNum > 0)
        {
            $historyData = (new AiChatRecordDetails())->getChatHistoryList($msgData['chat_id'], $msgData['parent_chat_detail_id'], $historyNum, $configData['sl_id']);
        }
        $queryParamData = [
            'uid' => $configData['uid'],
            'ia_type' => $resConfig['ia_type'],
            'query' => $msgData['msg'],
            'chat_history' => $historyData ?? [],
            'name' => $msgData['name'],
            'sex' => $resConfig['sex'],
            'ask' => $resConfig['ask'],
            'chat_type' => $resConfig['chat_type'],
            'data_info' => $resConfig['data_info'],
        ];
        // 这行代码用于关闭输出缓冲。关闭后，脚本的输出将立即发送到浏览器，而不是等待缓冲区填满或脚本执行完毕。
//        ini_set('output_buffering', 'off');

        // 这行代码禁用了 zlib 压缩。通常情况下，启用 zlib 压缩可以减小发送到浏览器的数据量，但对于服务器发送事件来说，实时性更重要，因此需要禁用压缩。
//        ini_set('zlib.output_compression', false);
        ignore_user_abort(true); // 忽略客户端断开连接
        ob_implicit_flush(true); // 开启隐式刷新
        // 这行代码使用循环来清空所有当前激活的输出缓冲区。ob_end_flush() 函数会刷新并关闭最内层的输出缓冲区，@ 符号用于抑制可能出现的错误或警告。
        try
        {
            while (ob_get_level() > 0 && @ob_end_flush())
            {
            }
        }
        catch (\Exception $e)
        {
        }
        // 这行代码设置 HTTP 响应的 Content-Type 为 text/event-stream，这是服务器发送事件（SSE）的 MIME 类型。
        header('Content-Type: text/event-stream');

        // 这行代码设置 HTTP 响应的 Cache-Control 为 no-cache，告诉浏览器不要缓存此响应。
        header('Cache-Control: no-cache');

        // 这行代码设置 HTTP 响应的 Connection 为 keep-alive，保持长连接，以便服务器可以持续发送事件到客户端。
        header('Connection: keep-alive');

        header('X-Accel-Buffering: no');//这一行必须存在，否则不好使（X-Accel-Buffering 头信息设置为“no”，表示已经禁用缓冲机制，服务器会立即发送响应数据，以确保客户端能够尽早地接收到数据。而如果设置为“yes”或不设置该头信息，则表示启用缓冲机制，服务器会将响应数据写入缓冲区，然后批量发送给客户端。)

        $resData = Curl::requestStream($url, $queryParamData, 'POST', ['Content-Type' => 'application/json', 'stream' => true], function ($stream)
        {
            $resStr = '';
            while (!$stream->eof())
            {
                $res = $stream->read(1); // 每次读取 1 字节，可以根据需求进行调整
                echo $res; // 输出一波数据
                flush(); //刷新缓存（直接发送到浏览器）

                $resStr .= $res;
            }

            return $resStr;
        }, 'json');
        $resData['question'] = $msgData['msg'];
        $resData['chat_id'] = $msgData['chat_id'];
        $resData['chat_record_id'] = $msgData['chat_detail_id'];
        // 添加记录
        Db::table('ai_chat_room.ai_chat_python_result_log')->insert(['chat_id' => $msgData['chat_id'], 'chat_record_id' => $msgData['chat_detail_id'], 'result' => json_encode($resData, JSON_UNESCAPED_UNICODE), 'create_time' => time()]);

        if ($resData['success'])
        {
            $queryParamData['chat_history'][] = [
                'role' => 'user',
                'content' => $msgData['msg'],
            ];
            $queryParamData['chat_history'][] = [
                'role' => 'assistant',
                'content' => $resData['data'],
            ];
            unset($queryParamData['query'], $queryParamData['uid']);
            $queryParamData['chat_detail_id'] = $msgData['chat_detail_id'];
            $lastData = [
                'uid' => $configData['uid'],
                'chat_id' => $msgData['chat_id'],
                'content' => addslashes(json_encode($queryParamData, JSON_UNESCAPED_UNICODE)),
                'create_time' => time(),
            ];
            // 记录最后一次请求信息  写入或更新 用户uid数据存在时进行自动更新 否则进行新增写入
            Db::execute("INSERT INTO `ai_chat_room`.`ai_chat_user_last_chat_data` (`uid`, `chat_id`, `content`,`create_time`) VALUES ({$lastData['uid']}, {$lastData['chat_id']}, '{$lastData['content']}',{$lastData['create_time']}) ON DUPLICATE KEY UPDATE chat_id = {$lastData['chat_id']}, content = '{$lastData['content']}',create_time = {$lastData['create_time']};");

            return $resData['data'];
        } else
        {
            return '';
        }

        return '';
    }

    /**
     * 重载 配置数据
     * @param array $configData
     * @return array
     */
    public static function resertConfigData(array $configData)
    {
        $resData = [
            'ia_type' => $configData['type'] - 1,
            'ask' => $configData['config']['desc'],
        ];
        $config = $configData['config']['config'];
        $tagIds = [];
        foreach ($config as $item)
        {
            $tagIds = array_merge($tagIds, $item['ids']);
        }
        $tagData = (new AiChatTag())->batchGetInfoByIds($tagIds, ['name']);
        $sex = current($config['sex']['ids']);
        $sexTypeId = current($config['sex_type']['ids']);
        $resData['chat_type'] = $tagData[$sexTypeId]['name'];
        $resData['sex'] = $tagData[$sex]['name'];
        $dataInfo = null;
        switch ($configData['type'])
        {
            case 1:
                $courtship = [];
                foreach ($config['option10']['ids'] as $idItem)
                {
                    $courtship[] = $tagData[$idItem]['name'];
                }
                $emotionalNeeds = [];
                foreach ($config['option20']['ids'] as $idItem)
                {
                    $emotionalNeeds[] = $tagData[$idItem]['name'];
                }
                $dataInfo = [
                    'courtship' => implode('，', $courtship),    // 你希望你和TA当前的恋爱阶段是
                    'emotional_needs' => implode('，', $emotionalNeeds),  // 你的情感需求是
                    'story' => $configData['story_line_content'],    // 剧情
                ];
                break;
            case 2:
                $emotionalState = [];
                foreach ($config['option10']['ids'] as $idItem)
                {
                    $emotionalState[] = $tagData[$idItem]['name'];
                }
                $heart = [];
                foreach ($config['option11']['ids'] as $idItem)
                {
                    $heart[] = $tagData[$idItem]['name'];
                }
                $feel = [];
                foreach ($config['option20']['ids'] as $idItem)
                {
                    $feel[] = $tagData[$idItem]['name'];
                }
                $emotionalNeeds = [];
                foreach ($config['option30']['ids'] as $idItem)
                {
                    $emotionalNeeds[] = $tagData[$idItem]['name'];
                }
                $bring = [];
                foreach ($config['expectation']['ids'] as $idItem)
                {
                    $bring[] = $tagData[$idItem]['name'];
                }
                $dataInfo = [
                    'emotional_state' => implode('，', $emotionalState),    // 你当前的感情状态是
                    'heart' => implode('，', $heart),  // 你的内心是
                    'feel' => implode('，', $feel),  // 你对当前感情状态的感受
                    'emotional_needs' => implode('，', $emotionalNeeds),  // 你的情感需求
                    'bring' => implode('，', $bring),    // 你期待带来什么
                ];
                break;
            case 3:
                $emotionalDistress = [];
                foreach ($config['option10']['ids'] as $idItem)
                {
                    $emotionalDistress[] = $tagData[$idItem]['name'];
                }
                $level = [];
                foreach ($config['option20']['ids'] as $idItem)
                {
                    $level[] = $tagData[$idItem]['name'];
                }
                $bring = [];
                foreach ($config['expectation']['ids'] as $idItem)
                {
                    $bring[] = $tagData[$idItem]['name'];
                }
                $dataInfo = [
                    'emotional_distress' => implode('，', $emotionalDistress),    // 你目前更多的受到哪些情绪困扰?
                    'level' => implode('，', $level),  // 这种情绪困扰的严重程度如何?
                    'bring' => implode('，', $bring),    // 你期待带来什么
                ];
                break;
            case 4:
                $character = [];
                foreach ($config['option10']['ids'] as $idItem)
                {
                    $character[] = $tagData[$idItem]['name'];
                }
                $relType = [];
                foreach ($config['option20']['ids'] as $idItem)
                {
                    $relType[] = $tagData[$idItem]['name'];
                }
                $contactState = [];
                foreach ($config['option30']['ids'] as $idItem)
                {
                    $contactState[] = $tagData[$idItem]['name'];
                }
                $bring = [];
                foreach ($config['expectation']['ids'] as $idItem)
                {
                    $bring[] = $tagData[$idItem]['name'];
                }
                $dataInfo = [
                    'character' => implode('，', $character),    // 你认为你的性格更倾向于
                    'rel_type' => implode('，', $relType),  // 你目前想要改善的关系是以下哪种类型
                    'contact_state' => implode('，', $contactState),  // 你们当前的交往状态是
                    'bring' => implode('，', $bring),    // 你期待带来什么
                ];
                break;
            case 5:
                $workType = [];
                foreach ($config['option10']['ids'] as $idItem)
                {
                    $workType[] = $tagData[$idItem]['name'];
                }
                $level = [];
                foreach ($config['option20']['ids'] as $idItem)
                {
                    $level[] = $tagData[$idItem]['name'];
                }
                $idea = [];
                foreach ($config['option30']['ids'] as $idItem)
                {
                    $idea[] = $tagData[$idItem]['name'];
                }
                $bring = [];
                foreach ($config['expectation']['ids'] as $idItem)
                {
                    $bring[] = $tagData[$idItem]['name'];
                }
                $dataInfo = [
                    'work_type' => implode('，', $workType),    // 你当前的工作类型是
                    'level' => implode('，', $level),  // 你对当前的事业满意程度
                    'idea' => implode('，', $idea),  // 你当前的想法更倾向于
                    'bring' => implode('，', $bring),    // 你期待带来什么
                ];
                break;
            case 6:
                $hole = [];
                foreach ($config['option10']['ids'] as $idItem)
                {
                    $hole[] = $tagData[$idItem]['name'];
                }
                $bring = [];
                foreach ($config['expectation']['ids'] as $idItem)
                {
                    $bring[] = $tagData[$idItem]['name'];
                }
                $dataInfo = [
                    'hole' => implode('，', $hole),    // 你希望秘密树洞陪你一起
                    'bring' => implode('，', $bring),    // 你期待带来什么
                ];
                break;
        }
        $resData['data_info'] = $dataInfo;
        return $resData;
    }
}